"use strict";

/**
 * 提供表单元素初始化、加载提示、动画等公用方法
 */
let EApp = function () {
    // 状态色
    let colors = {};
    /**
     * 全局动画设置
     *
     * @type {{in: string, out: string}}
     */
    const animate = {
        // 出现动画
        in: 'fadeIn',
        // 消失动画
        out: 'fadeOut'
    };

    /**
     * 初始化 tooltips
     *
     * @param $element {object} 元素
     */
    let initTooltip = function ($element) {
        let skin = $element.data('skin') ? 'tooltip-' + $element.data('skin') : '';
        let width = $element.data('width') === 'auto' ? 'tooltop-auto-width' : '';
        let triggerValue = $element.data('trigger') ? $element.data('trigger') : 'hover';

        $element.tooltip({
            trigger: triggerValue,
            template: '<div class="tooltip ' + skin + ' ' + width + '" role="tooltip">\
                <div class="arrow"></div>\
                <div class="tooltip-inner"></div>\
            </div>'
        });
    };

    /**
     * 初始化 tooltips，将会自动初始化`[data-toggle="e-tooltip"]`和`.e-tooltip-auto`的元素
     */
    let initTooltips = function () {
        $('[data-toggle="e-tooltip"], .e-tooltip-auto').each(function () {
            initTooltip($(this));
        });
    };

    /**
     * 初始化 popover
     *
     * @param $element {object} 元素
     */
    let initPopover = function ($element) {
        let skin = $element.data('skin') ? 'popover-' + $element.data('skin') : '';
        let triggerValue = $element.data('trigger') ? $element.data('trigger') : 'hover';

        $element.popover({
            trigger: triggerValue,
            template: '\
            <div class="popover ' + skin + '" role="tooltip">\
                <div class="arrow"></div>\
                <h3 class="popover-header"></h3>\
                <div class="popover-body"></div>\
            </div>'
        });
    };

    /**
     * 初始化 popover，将会自动初始化`[data-toggle="e-popover"]`和`.e-popover-auto`的元素
     */
    let initPopovers = function () {
        $('[data-toggle="e-popover"], .e-popover-auto').each(function () {
            initPopover($(this));
        });
    };

    /**
     * 初始化滚动条插件`PerfectScrollbar`
     */
    let initScroll = function () {
        $('[data-scroll="true"], .e-scrollable').each(function () {
            let $element = $(this);
            EUtil.scrollInit(this, {
                mobileNativeScroll: true,
                handleWindowResize: true,
                height: function () {
                    if (EUtil.isInResponsiveRange('tablet-and-mobile') && $element.data('mobile-height')) {
                        return $element.data('mobile-height');
                    } else {
                        return $element.data('height');
                    }
                }
            });
        });
    };

    /**
     * 初始化 Card
     *
     * @param element {element|string} 目标元素，支持`选择器`、`Element`、`jQuery对象`
     * @param options {object} 选项
     */
    let initCard = function (element, options) {
        new ECard(element, options);
    };

    /**
     * 初始化 Card，将会默认初始化`[data-card="true"]`的元素
     */
    let initCards = function () {
        $('[data-card="true"]').each(function () {
            let $el = $(this);
            if ($el.data('data-card-initialized') !== true) {
                initCard(this, {});
                $el.data('data-card-initialized', true);
            }
        });
    };

    /**
     * 初始化 Alert 的关闭按钮，点击`[data-close=alert]`将隐藏Alert
     */
    let initAlerts = function () {
        $('body').on('click', '[data-close=alert]', function () {
            $(this).closest('.alert').hide();
        });
    };

    /**
     * 处理插件（select、input）值改变时执行表单验证
     *
     * @param $element {object} jQuery元素
     */
    let handleValidate = function ($element) {
        let $form = $element.parents('.e-form');
        let validate = EUtil.data($form).get('validate');
        if (validate) {
            validate.element($element);
        }
    };

    /**
     * 初始化bootstrap select
     * @param selector {string} 选择器
     */
    let initSelectPicker = function (selector) {
        let _initSelectPicker = function ($element) {
            let placeholder = $element.data('placeholder');
            $element.selectpicker({
                noneSelectedText: EUtil.isNotBlank(placeholder) ? placeholder : ''
            }).on('changed.bs.select', function () {
                handleValidate($element);
            });
        };
        $(selector).each(function () {
            let $element = $(this);
            if (!$element.data('select-initialized')) {
                $element.attr('data-select-initialized', 'true');

                // 指定了字典类型
                if (EUtil.isNotBlank($element.data('dict-type'))) {
                    if ($element.data('no-empty') !== true) {
                        $element.append('<option value=""></option>');
                    }
                    initDictSelect($element);
                }
                // 指定了 data-url 属性,ajax请求接口获取下拉菜单
                if (EUtil.isNotBlank($element.data('url'))) {
                    if ($element.data('no-empty') !== true) {
                        $element.append('<option value=""></option>');
                    }
                    initSelectByUrl($element, function ($element) {
                        _initSelectPicker($element);
                    });
                } else {
                    let defaultValue = $element.data('value');
                    if(EUtil.isNotBlank(defaultValue)){
                        if ('multiple' === $element.attr('multiple')) {
                            if(!EUtil.isString(defaultValue)){
                                defaultValue = defaultValue + '';
                            }
                            $element.val(defaultValue.split(','));
                        } else {
                            $element.val(defaultValue);
                        }
                    }
                    _initSelectPicker($element);
                }
            }
        });
    };

    /**
     * 初始化select2
     *
     * @param selector {string} 选择器
     */
    let initSelect2Picker = function (selector) {
        let _initSelectPicker = function ($element) {
            $element.select2({
                placeholder: $element.attr('title'),
                // 多选时最多可以选择几个
                maximumSelectionLength: $element.data('max-options'),
                // 是否显示搜索框
                minimumResultsForSearch: $element.data('live-search') ? 0 : Infinity,
                tags: $element.data('tags') // 是否可添加标签
            });
        };

        $(selector).each(function () {
            let $element = $(this);
            if (!$element.data('select-initialized')) {
                $element.attr('data-select-initialized', 'true');

                // 指定了字典类型
                if (EUtil.isNotBlank($element.data('dict-type'))) {
                    if ($element.data('no-empty') !== true) {
                        $element.append('<option value=""></option>');
                    }
                    initDictSelect($element);
                }
                // 指定了 data-url 属性,ajax请求接口获取下拉菜单
                if (EUtil.isNotBlank($element.data('url'))) {
                    if ($element.data('no-empty') !== true) {
                        $element.append('<option value=""></option>');
                    }
                    initSelectByUrl($element, function ($element) {
                        _initSelectPicker($element);
                    });
                } else {
                    if (EUtil.isNotBlank($element.data('value'))) {
                        $element.val($element.data('value'));
                    }
                    _initSelectPicker($element);
                }
            }
        });
    };
    /**
     * 初始化input-mask
     *
     * @param selector {string} 选择器
     */
    let initInputMask = function (selector) {
        $(selector).each(function () {
            let $element = $(this);
            if (!$element.data('select-initialized')) {
                $element.attr('data-select-initialized', 'true');
                $element.inputmask({
                    mask: $element.data('mask'),
                    placeholder: $element.data('placeholder')
                });
            }
        });
    };
    /**
     * 初始化auto-size
     *
     * @param selector {string} 选择器
     */
    let initAutoSize = function (selector) {
        $(selector).each(function () {
            let $element = $(this);
            if (!$element.data('select-initialized')) {
                $element.attr('data-select-initialized', 'true');
                autosize($element);
            }
        });
    };
    /**
     * 初始化Clipboard
     *
     * @param selector {string} 选择器
     */
    let initClipboard = function (selector) {
        new ClipboardJS(selector).on('success', function (e) {
            e.clearSelection();
        });
    };
    /**
     * 初始化 Form Validate
     *
     * @param selector {string} 选择器
     */
    let initFormValidate = function (selector) {
        $(selector).each(function () {
            let $element = $(this);
            let validate;
            if (!EUtil.data($element).has('validate')) {
                // 初始化并放到全局缓存，bootstrap-select和select2会用到
                validate = $element.validate({
                    invalidHandler: function (event, validator) {
                        if (validator.errorList.length) {
                            // 有错误，滚动到错误处
                            EUtil.scrollTo(null, Math.max($(validator.errorList[0].element).offset().top - 25, 0));
                        }
                    }
                });
                EUtil.data($element).set('validate', validate);
            }
        });
    };

    /**
     * 初始化checkbox字典
     *
     * @param selector {string} jquery选择器
     */
    let initCheckbox = function (selector) {
        initCheckBoxOrRadio($(selector), 'checkbox');
    };
    /**
     * 初始化radio字典
     *
     * @param selector {string} jquery选择器
     */
    let initRadio = function (selector) {
        initCheckBoxOrRadio($(selector), 'radio');
    };
    /**
     * 初始化checkbox/radio字典
     *
     * @param $elements {object} jquery元素
     * @param type {string} 类型
     */
    let initCheckBoxOrRadio = function ($elements, type) {
        let defaultChecked = function (value, code) {
            if (EUtil.isNumber(value)) {
                try {
                    code = Number(code);
                } catch (e) {
                }
                if (value === code) {
                    return 'checked';
                }
            } else {
                if (EUtil.isNotBlank(value)) {
                    let values = value.split(',');
                    if (values.indexOf(code) > -1) {
                        return 'checked';
                    }
                }
            }
            return '';
        };
        if ($elements != null && $elements.length > 0) {
            $($elements).each(function (index, element) {
                let $element = $(element);
                // 检查是否初始化过
                if (!$element.data(type + '-initialized')) {
                    $element.attr('data-' + type + '-initialized', 'true');
                    // 字典类型
                    let dictType = $element.data('dict-type');
                    if (EUtil.isNotBlank(dictType)) {
                        // 方向
                        let direction = $element.data('direction');
                        let containerClass = 'e-' + type + '-inline';
                        if ('vertical' === direction) {
                            containerClass = 'e-' + type + '-list';
                        }
                        let dicts = ETool.getSysDictArrayByDictType(dictType);
                        if (dicts != null && dicts.length > 0) {
                            let value = $element.data('value');
                            let name = $element.data('name');
                            let required = $element.data('required');
                            let html = '<div class="' + containerClass + '">';
                            $(dicts).each(function (index, dict) {
                                html += '<label class="e-' + type + '">\
                                        <input name="' + name + '" value="' + dict.code + '" type="' + type + '" ' +
                                    defaultChecked(value, dict.code) + ' ' + (required ? 'required' : '') + '> ' + dict.name + '\
                                        <span></span>\
                                    </label>';
                            });
                            html += '</div>';
                            $element.html(html);
                        }
                    }
                }
            });
        }
    };
    /**
     * 初始化日期插件
     *
     * @param selector {string} 选择器
     */
    let initDateTimePicker = function (selector) {
        /**
         * 获取默认视图
         * 0-分 1-时 2-日 3-月 4-年
         * @param format {string} 日期格式
         * @return {number}
         */
        function getStartView(format) {
            if (format === 'yyyy') {
                return 4;
            } else if (format.length === 'yyyy-mm'.length) {
                return 3;
            } else if (format.length === 'hh:ii'.length || format.length === 'hh:ii:ss'.length) {
                return 1;
            } else {
                return 2;
            }
        }

        /**
         * 获取最小视图
         * 0-分 1-时 2-日 3-月 4-年
         * @param format {string} 日期格式
         * @return {number}
         */
        function getMinView(format) {
            if (format === 'yyyy') {
                return 4;
            } else if (format.length === 'yyyy-mm'.length) {
                return 3;
            } else if (format.length === 'yyyy-mm-dd'.length) {
                return 2;
            } else if (format.length === 'yyyy-mm-dd hh'.length || format === 'yyyy-mm-dd hh:00') {
                return 1;
            } else {
                return 0;
            }
        }

        // default
        let defaultOptions = {
            language: 'zh-CN',
            todayHighlight: true, // 高亮今日
            autoclose: true, // 自动关闭
            todayBtn: false, // 显示今日按钮
            format: 'yyyy-mm-dd',
            pickerPosition: 'bottom-right'
        };
        $(selector).each(function () {
            let $element = $(this);
            let options = {
                pickerPosition: $element.data('position'),
                format: $element.data('format'),
                todayBtn: $element.data('show-today'),
                startView: $element.data('start-view'),
                minView: $element.data('min-view')
            };
            options = $.extend(true, {}, defaultOptions, options);
            if (typeof options.startView === 'undefined') {
                options.startView = getStartView(options.format);
            }
            if (typeof options.minView === 'undefined') {
                options.minView = getMinView(options.format);
            }
            $element.datetimepicker(options).change(function () {
                handleValidate($element);
            });
        });
    };
    /**
     * 初始化日期范围
     *
     * @param selector {string} 选择器
     */
    let initDateRange = function (selector) {
        $(selector).each(function () {
            // 查找div内的input，必须为2个，如果不是2个则忽略不进行初始化
            let $inputs = $(this).find('input[type="text"]');
            if ($inputs.length === 2) {
                // 插件已经在initTimePicker中初始化，所以这里只需在changeDate event时更改startDate/endDate
                // 请在日期插件初始化后调用initDateRange
                let $strDate = $($inputs[0]),
                    $endDate = $($inputs[1]);
                $strDate.on('changeDate', function (ev) {
                    let strDate = ev.date;
                    if (EUtil.isNotBlank(strDate)) {
                        $endDate.datetimepicker('setStartDate', strDate);
                    } else {
                        $endDate.datetimepicker('setStartDate', null);
                    }
                });

                $endDate.on('changeDate', function (ev) {
                    let endDate = ev.date;
                    if (EUtil.isNotBlank(endDate)) {
                        $strDate.datetimepicker('setEndDate', endDate);
                    } else {
                        $strDate.datetimepicker('setEndDate', null);
                    }
                });
            }
        });
    };
    /**
     * 初始化日期范围插件
     *
     * @param selector {string} 选择器
     */
    let initDateRangePicker = function (selector) {
        // default
        let defaultOptions = {
            buttonClasses: 'btn',
            applyClass: 'btn-brand',
            cancelClass: 'btn-secondary',
            autoUpdateInput: false, // 不自动填充内容
            locale: {
                cancelLabel: '取消',
                applyLabel: '确定',
                format: 'YYYY-MM-DD'
            },
            timePicker: false, // 是否显示时间
            timePickerIncrement: 10 // 增量
        };
        $(selector).each(function () {
            if (typeof $.fn.daterangepicker === 'undefined' && EDebug) {
                console.warn('EApp.initDateRangePicker缺少Bootstrap Date Range Picker');
                return;
            }
            let $element = $(this);
            let options = {
                timePicker: $element.data('time'),
                timePickerIncrement: $element.data('time-increment'),
                startDate: $element.data('start-date'),
                endDate: $element.data('end-date'),
                locale: {
                    format: $element.data('format')
                }
            };
            options = $.extend(true, {}, defaultOptions, options);
            // 默认值，date-*-date优先级高于value
            if (EUtil.isBlank(options.startDate) && EUtil.isBlank(options.endDate) && EUtil.isNotBlank($element.val())) {
                let dates = $element.val().split('~');
                if (dates.length !== 2) {
                    return;
                }
                options.startDate = $.trim(dates[0]);
                options.endDate = $.trim(dates[1]);
            }
            // 将字符串日期格式转为Date类型，依赖于moment.js
            if (EUtil.isNotBlank(options.startDate) && EUtil.isNotBlank(options.endDate)) {
                try {
                    options.startDate = moment(options.startDate, options.locale.format);
                    options.endDate = moment(options.endDate, options.locale.format);
                    $element.val(options.startDate.format(options.locale.format) + ' ~ ' + options.endDate.format(options.locale.format));
                } catch (e) {
                    console.error(e);
                    return;
                }
            }

            $element.daterangepicker(options, function (start, end, label) {
                $element.val(start.format(options.locale.format) + ' ~ ' + end.format(options.locale.format));
                handleValidate($element);
            });
        });
    };

    /**
     * 初始化时间插件
     *
     * @param selector {string} 选择器
     */
    let initTimePicker = function (selector) {
        // default
        let defaultOptions = {
            minuteStep: 1, // 增/减量
            showSeconds: false, // 显示秒
            showMeridian: false // 是否使用12小时模式
        };
        $(selector).each(function () {
            if (typeof $.fn.timepicker === 'undefined' && EDebug) {
                console.warn('EApp.initTimePicker缺少Bootstrap Time Picker');
                return;
            }
            let $element = $(this);
            let options = {
                defaultTime: $element.val(),
                showSeconds: $element.data('show-seconds'), // 是否显示单位-秒
                showMeridian: $element.data('show-meridian') // true 12hr mode、false 24hr mode
            };
            options = $.extend(true, {}, defaultOptions, options);
            $element.timepicker(options);
        });
    };
    /**
     * 初始化TouchSpin插件
     *
     * @param selector {string} 选择器
     */
    let initTouchSpin = function (selector) {
        // default
        let defaultOptions = {
            buttondown_class: 'btn btn-secondary',
            buttonup_class: 'btn btn-secondary',
            verticalup: '<i class="la la-plus"></i>',
            verticaldown: '<i class="la la-minus"></i>'
        };
        $(selector).each(function () {
            if (typeof $.fn.TouchSpin === 'undefined' && EDebug) {
                console.warn('EApp.initTouchSpin缺少Bootstrap TouchSpin');
                return;
            }
            let $element = $(this);
            let options = {
                prefix: $element.data('prefix'), // 前缀
                postfix: $element.data('postfix'), // 后缀
                min: $element.data('min'),
                max: $element.data('max'),
                step: $element.data('step'), // 递增/减量
                decimals: $element.data('decimals'), // 小数位数
                boostat: $element.data('boostat'), // 第n步后加速
                maxboostedstep: $element.data('maxboostedstep'), // 加速最大倍数
                verticalbuttons: $element.data('vertical')
            };
            options = $.extend(true, {}, defaultOptions, options);
            $element.TouchSpin(options);
        });
    };
    /**
     * 初始化MaxLength插件
     *
     * @param selector {string} 选择器
     */
    let initMaxLength = function (selector) {
        $(selector).each(function () {
            let $element = $(this);
            let options = {
                separator: ' 个字符，可输入 ',
                preText: '已输入 ',
                postText: ' 个字符',
                validate: true,
                warningClass: 'badge badge-brand badge--inline',
                limitReachedClass: 'badge badge-brand badge--inline'
            };
            $element.maxlength(options);
        });
    };

    /**
     * 根据字典类型加载select > option
     *
     * @param $element {object} select对象
     */
    let initDictSelect = function ($element) {
        let dictType = $element.data('dict-type');
        let dicts = ETool.getSysDictArrayByDictType(dictType);
        if (dicts != null && dicts.length > 0) {
            // 倒序排列？
            let isReverse = $element.data('reverse');
            if(isReverse){
                dicts = dicts.reverse();
            }
            $(dicts).each(function (index, dict) {
                $element.append('<option value="' + dict.code + '">' + dict.name + '</option>');
            });
        }
    };
    /**
     * 根据 data-url 加载select > option
     *
     * @param $element {object} 元素
     * @param callback {function} 回调
     */
    let initSelectByUrl = function ($element, callback) {
        EUtil.ajax({
            url: $element.data('url'),
            fail: function (res) {
                console.error(res.message);
                if (EUtil.isFunction(callback)) {
                    callback($element);
                }
            },
            success: function (res) {
                if (typeof res.data !== 'undefined' && res.data.length > 0) {
                    $(res.data).each(function (index, obj) {
                        $element.append('<option value="' + obj.value + '">' + obj.text + '</option>');
                    });
                }
                if (EUtil.isNotBlank($element.data('value'))) {
                    $element.val($element.data('value'));
                }
                if (EUtil.isFunction(callback)) {
                    callback($element);
                }
            }
        });
    };
    /**
     * 合并默认Dropzone参数
     *
     * @param options {object} 参数
     * @return {object} 合并后参数
     */
    let extendDropzoneDefaultOption = function (options) {
        let _defaultOptions = {
            url: basePath + '/auth/upload',
            paramName: "file",
            maxFiles: 1,
            maxFilesize: 10, // MB
            addRemoveLinks: true,
            autoQueue: true,
            dictDefaultMessage: Dropzone.dictDefaultMessage,
            dictFallbackMessage: Dropzone.dictFallbackMessage,
            dictFallbackText: Dropzone.dictFallbackText,
            dictFileTooBig: Dropzone.dictFileTooBig,
            dictInvalidFileType: Dropzone.dictInvalidFileType,
            dictResponseError: Dropzone.dictResponseError,
            dictCancelUpload: Dropzone.dictCancelUpload,
            dictUploadCanceled: Dropzone.dictUploadCanceled,
            dictCancelUploadConfirmation: Dropzone.dictCancelUploadConfirmation,
            dictRemoveFile: Dropzone.dictRemoveFile,
            dictMaxFilesExceeded: Dropzone.dictMaxFilesExceeded
        };
        return $.extend(true, {}, _defaultOptions, options);
    };

    return {
        init: function () {
            // 移除页面加载中class
            EApp.removePageLoading();
            // 初始化插件
            EApp.initComponents();
        },
        /**
         * 初始化插件
         */
        initComponents: function () {
            // 滚动条
            initScroll();
            // 卡片
            initCards();
            // 文字提示
            initTooltips('.e-tooltip, [data-toggle="e-tooltip"]');
            // 气泡提示
            initPopovers('.e-popover, [data-toggle="e-popover"]');
            // 提示（关闭）
            initAlerts();
            // Bootstrap Select 下拉
            initSelectPicker('.select-picker');
            // Select2 下拉
            initSelect2Picker('.select2-picker');
            // 字典checkbox
            initCheckbox('.checkbox-dict');
            // 字典radio
            initRadio('.radio-dict');
            // 日期时间
            initDateTimePicker('.date-picker');
            // 起始日期 基于上面插件，请勿改变调用顺序
            initDateRangePicker('.date-range-picker');
            // 时间插件
            initTimePicker('.time-picker');
            // 日期范围
            initDateRange('.input-date-range');
            // TouchSpin
            initTouchSpin('.touch-spin');
            // 最大长度
            initMaxLength('.max-length');
            // 输入格式
            initInputMask('.input-mask');
            // 自动大小
            initAutoSize('.auto-size');
            // 剪切板
            initClipboard('.clipboard');
            // 表单验证
            initFormValidate('.e-form');
        },
        /**
         * 初始化radio
         */
        initRadio: function () {
            initRadio('.radio-dict');
        },
        /**
         * 初始化checkbox
         */
        initCheckbox: function () {
            initCheckbox('.checkbox-dict');
        },
        /**
         * 初始化tooltips
         */
        initTooltips: function () {
            initTooltips();
        },
        /**
         * 初始化tooltip
         *
         * @param el {object} 要初始化的元素
         */
        initTooltip: function (el) {
            initTooltip(el);
        },
        /**
         * 初始化popovers
         */
        initPopovers: function () {
            initPopovers();
        },
        /**
         * 初始化popover
         *
         * @param el {object} 要初始化的元素
         */
        initPopover: function (el) {
            initPopover(el);
        },
        /**
         * 初始化bootstrap select
         *
         * @param selector {string} 选择器
         */
        initSelectPicker: function (selector) {
            return initSelectPicker(selector);
        },
        /**
         * 初始化select2
         *
         * @param selector {string} 选择器
         */
        initSelect2Picker: function (selector) {
            initSelect2Picker(selector);
        },
        /**
         * 初始化input-mask
         *
         * @param selector {string} 选择器
         */
        initInputMask: function (selector) {
            initInputMask(selector);
        },
        /**
         * 初始化日期插件
         *
         * @param selector {string} 选择器
         */
        initDateTimePicker: function (selector) {
            initDateTimePicker(selector);
        },
        /**
         * 初始化日期范围插件
         *
         * @param selector {string} 选择器
         */
        initDateRangePicker: function (selector) {
            initDateRangePicker(selector);
        },
        /**
         * 初始化日期周期
         *
         * @param selector {string} 选择器
         */
        initDateRange: function (selector) {
            initDateRange(selector);
        },
        /**
         * 初始化时间插件
         *
         * @param selector {string} 选择器
         */
        initTimePicker: function (selector) {
            initTimePicker(selector);
        },
        /**
         * 初始化文件上传
         *
         * @param options {object} 参数
         * @returns {object} Dropzone
         */
        initDropzone: function (options) {
            options = extendDropzoneDefaultOption(options);
            if (EUtil.isFunction(options.success)) {
                options._success = options.success;
            }
            options.success = function (file) {
                if (options._success) {
                    options._success($.parseJSON(file.xhr.response), file);
                }
                if (file.previewElement) {
                    return file.previewElement.classList.add("dz-success");
                }
            }
            if (EUtil.isFunction(options.complete)) {
                options._complete = options.complete;
            }

            options.complete = function (file) {
                if (options._complete) {
                    options._complete($.parseJSON(file.xhr.response), file);
                }
                if (file._removeLink) {
                    file._removeLink.innerHTML = this.options.dictRemoveFile;
                }
                if (file.previewElement) {
                    return file.previewElement.classList.add("dz-complete");
                }
            }
            return new Dropzone(options.selector, options);
        },

        /**
         * 初始化文件上传
         *
         * @param options {object} 参数
         * @returns {object} Dropzone
         */
        initMiniDropzone: function (options) {
            options = extendDropzoneDefaultOption(options);
            if (typeof options.autoQueue === 'undefined') {
                options.autoQueue = false;
            }
            // 不显示默认的移除按钮
            options.addRemoveLinks = false;
            // 上传列队放置位置
            options.previewsContainer = options.selector + ' .dropzone-items';
            // 选择文件按钮
            options.clickable = options.selector + ' .dropzone-select';
            // 文件列队模板
            options.previewTemplate = '\
            <div class="dropzone-item">\
                <div class="dropzone-file">\
                    <div class="dropzone-filename"><span data-dz-name>文件名称</span> <strong>(<span  data-dz-size>大小</span>)</strong></div>\
                    <div class="dropzone-error" data-dz-errormessage></div>\
                </div>\
                <div class="dropzone-progress">\
                    <div class="progress">\
                        <div class="progress-bar e-bg-brand" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0" data-dz-uploadprogress></div>\
                    </div>\
                </div>\
                <div class="dropzone-toolbar">\
                    <span class="dropzone-start"><i class="flaticon2-arrow"></i></span>\
                    <span class="dropzone-cancel" data-dz-remove style="display: none;"><i class="flaticon2-cross"></i></span>\
                    <span class="dropzone-delete" data-dz-remove><i class="flaticon2-cross"></i></span>\
                </div>\
            </div>';

            if (EUtil.isFunction(options.success)) {
                options._success = options.success;
                options.success = function (file) {
                    options._success($.parseJSON(file.xhr.response), file);
                }
            }
            if (EUtil.isFunction(options.complete)) {
                options._complete = options.complete;
                options.complete = function (file) {
                    options._complete($.parseJSON(file.xhr.response), file);
                }
            }
            let dropzone = new Dropzone(options.selector, options);

            // 选择文件
            dropzone.on('addedfile', function (file) {
                // 开始上传
                file.previewElement.querySelector(options.selector + ' .dropzone-start').onclick = function () {
                    dropzone.enqueueFile(file);
                };
                // 显示全部上传和全部移除按钮
                $(options.selector + ' .dropzone-upload, ' + options.selector + ' .dropzone-remove-all').css('display', 'inline-block');
            });

            // 每个文件发送之前调用
            dropzone.on('sending', function (file) {
                // 显示进度条
                $(options.selector + ' .progress-bar').css('opacity', '1');
                // 禁用开始上传按钮
                file.previewElement.querySelector(options.selector + ' .dropzone-start').setAttribute('disabled', 'disabled');
            });

            // 上传成功或错误时调用
            dropzone.on('complete', function (file) {
                // 隐藏进度、上传按钮
                let thisProgressBar = options.selector + ' .dz-complete';
                setTimeout(function () {
                    $(thisProgressBar + ' .progress-bar, ' + thisProgressBar + ' .progress, ' + thisProgressBar + ' .dropzone-start').css('opacity', '0');
                }, 300);
                if ('success' === file.status) {
                    setTimeout(function () {
                        // 防止短时间内多个文件同时上传导致一次性全部消失无动画，一个一个删除
                        let $animateElement = $(thisProgressBar + ':not(.dz-error):not(.animated):eq(0)').addClass('animated');
                        if ($animateElement.length) {
                            EApp.animateCSS($animateElement[0], 'fadeOut', function () {
                                console.log('end');
                                $animateElement.remove();
                            });
                        }
                    }, 500);
                }
            });

            // 上传全部
            $(options.selector + ' .dropzone-upload').click(function () {
                dropzone.enqueueFiles(dropzone.getFilesWithStatus(Dropzone.ADDED));
            });

            // 移除全部
            $(options.selector + ' .dropzone-remove-all').click(function () {
                $(options.selector + ' .dropzone-upload, ' + options.selector + ' .dropzone-remove-all').css('display', 'none');
                dropzone.removeAllFiles(true);
            });

            // 队列中的所有文件完成上传
            dropzone.on('queuecomplete', function () {
                $(options.selector + ' .dropzone-upload').css('display', 'none');
            });

            // 从列表中删除文件
            dropzone.on('removedfile', function (file) {
                if (dropzone.files.length < 1) {
                    $(options.selector + ' .dropzone-upload, ' + options.selector + ' .dropzone-remove-all').css('display', 'none');
                }
            });
            return dropzone;
        },

        /**
         * 显示加载提示
         *
         * @param target {string} 选择器
         * @param options {object} 选项
         */
        block: function (target, options) {
            let el = $(target);

            options = $.extend(true, {
                opacity: 0.5,
                overlayColor: '#fff',
                type: 'grow',
                state: 'success',
                size: 'sm',
                centerX: true,
                centerY: true,
                message: '',
                shadow: true,
                width: 'auto'
            }, options);

            let html;

            let type = options.type ? ' spinner-' + options.type : 'spinner-grow';
            let state = options.state ? ' e-font-' + options.state : 'e-font-brand';
            let size = options.size ? ' spinner-' + options.size : 'spinner-sm';

            let spinner = '<div class="' + type + size + state + '">\
                  <span class="sr-only">Loading...</span>\
                </div>';

            if (options.message && options.message.length > 0) {
                let classes = 'block-ui ' + (options.shadow === false ? 'block-ui-no-shadow' : '') + (options.size ? ' block-ui-' + options.size : '');
                spinner = '<span class="' + type + size + state + '"></span><span class="spinner-message">' + options.message + '</span>';
                html = '<div class="' + classes + '">' + spinner + '</div>';

                // 计算宽度
                let $temporary = $('<div/>').addClass(classes).html(spinner).css({
                    position: 'absolute',
                    visibility: 'hidden',
                    display: 'table'
                });
                $('body').append($temporary);
                options.width = $temporary.outerWidth() + 10;
                $temporary.remove();

                if (target === 'body') {
                    html = '<div class="' + classes + '" style="margin-left:-' + (options.width / 2) + 'px;">' + spinner + '</div>';
                }
            } else {
                html = spinner;
            }

            let params = {
                message: html,
                centerY: options.centerY,
                centerX: options.centerX,
                css: {
                    top: '30%',
                    left: '50%',
                    border: '0',
                    padding: '0',
                    backgroundColor: 'none',
                    width: options.width
                },
                overlayCSS: {
                    backgroundColor: options.overlayColor,
                    opacity: options.opacity,
                    cursor: 'wait',
                    zIndex: '10'
                },
                onUnblock: function () {
                    if (el && el[0]) {
                        el.css('position', '');
                        el.css('zoom', '');
                    }
                }
            };

            if (target === 'body') {
                params.css.top = '50%';
                $.blockUI(params);
            } else {
                let el = $(target);
                el.block(params);
            }
        },
        /**
         * 隐藏加载提示
         *
         * @param target {string} 选择器
         */
        unblock: function (target) {
            if (target && target !== 'body') {
                $(target).unblock();
            } else {
                $.unblockUI();
            }
        },
        /**
         * 显示页面级别加载提示
         *
         * @param options {object}
         */
        blockPage: function (options) {
            if (options == null) {
                options = {
                    message: '页面加载中，请稍候...'
                }
            }
            EApp.block('body', options);
        },
        /**
         * 隐藏页面级别加载提示
         */
        unblockPage: function () {
            return EApp.unblock('body');
        },
        /**
         * 在按钮上面显示加载中图标
         *
         * @param target {string|element} 选择器
         * @param options {object} 选项
         */
        progress: function (target, options) {
            let $btns = $(target);
            if ($btns.length) {
                $btns.each(function () {
                    let $element = $(this);
                    let type = (options && options.type) ? options.type : 'spinner-grow';
                    let color = (options && options.color) ? options.color : '';
                    let size = (options && options.size) ? 'spinner-' + options.size : 'spinner-sm';
                    let classes = 'e-spinner ' + type + ' ' + color + '' + size;
                    EApp.unProgress($element);
                    $element.attr('disabled', 'disabled').addClass('btn--spinner').html('<span class="' + classes + '" role="status" aria-hidden="true"></span>' + $element.html());
                });
            }
        },
        /**
         * 隐藏按钮上面显示加载中图标
         * @param target {string} 选择器
         */
        unProgress: function (target) {
            $(target).removeAttr('disabled').removeClass('btn--spinner').find('.e-spinner').remove();
        },
        /**
         * 根据状态名称获取颜色
         *
         * @param name {string} 状态名称
         * @return {string} 颜色
         */
        getStateColor: function (name) {
            return colors["state"][name];
        },
        /**
         * 获取base color
         *
         * @param type {string} 类型
         * @param level {number} 级别
         * @return {string} 颜色
         */
        getBaseColor: function (type, level) {
            return colors["base"][type][level - 1];
        },
        /**
         * 初始化标签页
         */
        initTabs: function () {
            window.tabPage = new ETabPage();
        },
        /**
         * 打开页面
         * @param name {string} 页面名称
         * @param url {string} 访问地址
         * @param canClose {boolean} 是否可以关闭
         * @param sourcePagePathname {string} 来源页面pathname，用于关闭标签页后返回来源页面
         */
        openPage: function (name, url, canClose, sourcePagePathname) {
            // 来源页面pathname
            if(EUtil.isBlank(sourcePagePathname)){
                sourcePagePathname = window.location.pathname;
            }
            if (top.location !== self.location && typeof tabPage === 'undefined') { // 有父页面,并且 tabPage is null
                parent.EApp.openPage(name, url, canClose, sourcePagePathname);
            } else {
                if (typeof tabPage !== 'undefined') {
                    tabPage.addTab(name, url, canClose, sourcePagePathname);
                } else {
                    window.open(url);
                }
            }
        },
        /**
         * 关闭当前页面
         */
        closeCurrentPage: function () {
            EApp.closeTabByUrl(window.location.pathname);
        },
        /**
         * 关闭指定url页面
         *
         * @param url {string} 页面url
         */
        closeTabByUrl: function (url) {
            if (top.location !== self.location && typeof tabPage === 'undefined') {
                // 有父页面,并且 tabPage is null
                parent.EApp.closeTabByUrl(url);
            } else {
                if (typeof tabPage !== 'undefined') {
                    tabPage.closeTabByUrl(url);
                } else {
                    window.close();
                }
            }
        },

        /**
         * 根据操作获取动画class
         *
         * @param {string} name in/out
         * @returns {string} class
         */
        getAnimate: function (name) {
            return animate[name];
        },
        /**
         * animate.css 工具
         *
         * @param selector {string} 展示动画的元素选择器
         * @param animationName {string} 动画名称
         * @param callback {function} 回调函数
         */
        animateCSS: function (selector, animationName, callback) {
            let node;
            if (typeof selector === 'string') {
                node = document.querySelector(selector);
            } else {
                node = selector;
            }

            node.classList.add('animated', animationName);

            function handleAnimationEnd() {
                node.classList.remove('animated', animationName);
                node.removeEventListener('animationend', handleAnimationEnd);

                if (EUtil.isFunction(callback)) {
                    callback.call();
                }
            }

            node.addEventListener('animationend', handleAnimationEnd);
        },
        /**
         * 移除页面加载中class
         */
        removePageLoading: function () {
            $('body').removeClass(cssPrefix + 'page--loading');
        }
    };
}();
// 初始化
$(document).ready(function () {
    EApp.init();
});
